<template>
  <div class="container">
    <div class="header">
      <div class="form-control">
        <input class="input input-alt" v-model="saveTitle" :placeholder="title" type="text">
        <span class="input-border input-border-alt"></span>
      </div>
      <div class="publishBtn">
        <button @click="openSubmitForm"><span class="text">发布</span><span>发布</span></button>
      </div>
    </div>
    <div class="main" style="border: 1px solid #ccc">
      <Toolbar
          style="border-bottom: 1px solid #ccc"
          :editor="editorRef"
          :defaultConfig="toolbarConfig"
          :mode="mode"
      />
      <Editor
          style="height:750px;"
          v-model="text"
          :defaultConfig="editorConfig"
          :mode="mode"
          @onCreated="handleEditorCreated"
          @onMaxLength="handleEditorMaxLength"
      />
    </div>
    <div style="padding:5px;">
      <span style="color:#757575;font-size: 14px">
        请尽量展现您的独特思维，创作属于自己的原创内容哦！期待您的精彩表现！
      </span>
    </div>
  </div>

  <!-- 文章发布对话框 -->
  <tiny-dialog-box top="33" v-model:visible="articleModalFlag" :title="formTitle" width="30%">
    <tiny-form
        :model="articleForm"
        label-position="top"
        label-width="100px"
    >
      <tiny-form-item label="标题" prop="title">
        <tiny-input v-model="articleForm.title"></tiny-input>
      </tiny-form-item>
      <tiny-form-item label="摘要" prop="coverImage">
        <tiny-input v-model="articleForm.description"></tiny-input>
      </tiny-form-item>
      <tiny-form-item label="类型" prop="type">
        <tiny-radio-group v-model="articleForm.type" :options="typeOptions"></tiny-radio-group>
      </tiny-form-item>
      <tiny-form-item label="标签" prop="tagList">
        <tiny-cascader-panel
            :options="tagList"
            v-model="tagValue"
            :props="cascaderProps"
            @change="handleChange"
        >
        </tiny-cascader-panel>
        <tiny-form-item>
          <tiny-tag
              v-for="(tag, index) in tagLabel"
              :key="index"
              effect="dark"
              type="info"
              style="margin-right:5px"
          >
            {{ tag }}
          </tiny-tag>
        </tiny-form-item>

      </tiny-form-item>
      <tiny-form-item label="封面图" prop="coverImage">
        <tiny-file-upload
            action="http://localhost:5173/api/file/upload"
            ref="pictureUpload"
            class="upload-demo picture-demo"
            list-type="picture-card"
            :limit="1"
            accept="image/*"
            @success="uploadSuccess"
        >
          <template #default>
            <tiny-icon-plus class="tiny-svg-size"/>
          </template>
          <template #file="{ file }">
            <div>
              <img class="tiny-upload-list__item-thumbnail" :src="file.url" alt=""/>
              <span class="tiny-upload-list__item-actions">
            <span class="tiny-upload-list__item-preview" @click="previewPicture(file)">
              <tiny-icon-view class="tiny-svg-size"/>
            </span>
            <span v-if="!disabled" class="tiny-upload-list__item-delete" @click="removePicture(file)">
              <tiny-icon-del class="tiny-svg-size"/>
            </span>
          </span>
            </div>
          </template>
        </tiny-file-upload>
        <tiny-dialog-box
            :visible="dialogVisible"
            width="50%"
            :modal="false"
            @close="closeImgPreviewPic"
        >
          <img style="width: 100%;height:100%;" :src="dialogImageUrl" alt="预览图片"/>
        </tiny-dialog-box>
      </tiny-form-item>
    </tiny-form>
    <template #footer>
      <tiny-button @click="articleModalFlag = false"> 取消</tiny-button>
      <tiny-button type="primary" @click="saveArticle"> 确定</tiny-button>
    </template>
  </tiny-dialog-box>

  <!-- 帖子发布对话框 -->
  <tiny-dialog-box top="33" v-model:visible="postModalFlag" :title="formTitle" width="30%">
    <tiny-form
        :model="postForm"
        label-position="top"
        label-width="100px"
    >
      <tiny-form-item label="标题" prop="title">
        <tiny-input v-model="postForm.title"></tiny-input>
      </tiny-form-item>
      <tiny-form-item label="专栏" prop="specialColumnId">
        <tiny-cascader
            filterable
            clearable
            v-model="postForm.specialColumnId"
            :options="columnList"
        >
          <template #empty>
            <div>没有选项</div>
          </template>
        </tiny-cascader>
      </tiny-form-item>
      <tiny-form-item label="封面图" prop="coverImage">
        <tiny-file-upload
            ref="pictureUpload"
            class="upload-demo picture-demo"
            list-type="picture-card"
            :limit="1"
            accept="image/*"
            action="http://localhost:5173/api/file/upload"
            @success="uploadSuccess"
        >
          <template #default>
            <tiny-icon-plus class="tiny-svg-size"/>
          </template>
          <template #file="{ file }">
            <div>
              <img class="tiny-upload-list__item-thumbnail" :src="file.url" alt=""/>
              <span class="tiny-upload-list__item-actions">
            <span class="tiny-upload-list__item-preview" @click="previewPicture(file)">
              <tiny-icon-view class="tiny-svg-size"/>
            </span>
            <span v-if="!disabled" class="tiny-upload-list__item-delete" @click="removePicture(file)">
              <tiny-icon-del class="tiny-svg-size"/>
            </span>
          </span>
            </div>
          </template>
        </tiny-file-upload>
        <tiny-dialog-box
            :visible="dialogVisible"
            width="50%"
            :modal="false"
            @close="closeImgPreviewPic"
        >
          <img style="width: 100%;height:100%;" :src="dialogImageUrl" alt="预览图片"/>
        </tiny-dialog-box>
      </tiny-form-item>
    </tiny-form>
    <template #footer>
      <tiny-button @click="postModalFlag = false"> 取消</tiny-button>
      <tiny-button type="primary" @click="savePost"> 确定</tiny-button>
    </template>
  </tiny-dialog-box>

</template>

<script setup>
import {onMounted, ref, onBeforeUnmount, shallowRef} from "vue";
import {useRoute, useRouter} from "vue-router";
import {
  Form as TinyForm,
  FormItem as TinyFormItem,
  Input as TinyInput,
  FileUpload as TinyFileUpload,
  DialogBox as TinyDialogBox,
  Cascader as TinyCascader,
  Button as TinyButton,
  RadioGroup as TinyRadioGroup, Modal,
  CascaderPanel as TinyCascaderPanel,
  Tag as TinyTag
} from '@opentiny/vue'
import {
  IconView,
  IconDel,
  IconPlus
} from '@opentiny/vue-icon'
import {userName, fileUploadToken} from "../config/index.js";
import request from '../utils/request.js'
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import {Editor, Toolbar} from '@wangeditor/editor-for-vue'


document.title = '内容发布'
const TinyIconView = IconView()
const TinyIconDel = IconDel()
const TinyIconPlus = IconPlus()
const route = useRoute()
const userId = route.query.userId
const router = useRouter()
const type = route.params.type
const title = ref('')
const text = ref('')
let articleModalFlag = ref(false)
let postModalFlag = ref(false)
const formTitle = ref('')
const saveTitle = ref('')
const coverImage = ref('')
const typeOptions = ref([
  {label: 0, text: '原创'},
  {label: 1, text: '转载'}
])
const currentUser = ref(localStorage.getItem(userName) ? JSON.parse(localStorage.getItem(userName)) : {})
const articleForm = ref({
  title: saveTitle.value,
  coverImage: coverImage.value,
  description: '',
  tagIdList: [],
  content: '',
  type: 0,
  userId: currentUser.value.id,
  createBy: currentUser.value.id,
  updateBy: currentUser.value.id
})
const postForm = ref({
  title: saveTitle.value,
  coverImage: '',
  specialColumnId: 0,
  userId: currentUser.value.id,
  createBy: currentUser.value.id,
  updateBy: currentUser.value.id
})
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const disabled = ref(false)
const pictureUpload = ref(null)
const columnList = ref([])
const tagList = ref([])
const tagValue = ref([])
const tagChildren = ref({})
const tagLabel = ref([])
const cascaderProps = {
  expandTrigger: 'hover',
  multiple: true
}
const editorRef = shallowRef()
const toolbarConfig = {
  excludeKeys: ['insertVideo', 'uploadVideo', 'editVideoSize']
}
const editorConfig = {
  placeholder: '请输入内容...',
  maxLength: 8192,
  MENU_CONF: {
    uploadImage: {
      fieldName: 'file',
      server: '/api/file/contentUpload',
      maxFileSize: 10 * 1024 * 1024, // 10M
      maxNumberOfFiles: 1,
      allowedFileTypes: ['image/*'],
      withCredentials: true,
      onSuccess: (file, res) => {
        console.log(`${file.name} 上传成功`, res)
      }
    }
  }
}
const mode = 'default' // 或 ‘simple’


// 处理超出最大长度
const handleEditorMaxLength = (editor) => {
  Modal.message({message: '内容字数超出最大长达8192', status: 'warning'})
}

// 编辑器创建
const handleEditorCreated = (editor) => {
  editorRef.value = editor
  console.log('@@@', editor.getAllMenuKeys())
}

// 保存帖子
const savePost = () => {
  postForm.value.coverImage = coverImage.value
  postForm.value.specialColumnId = postForm.value.specialColumnId[0]
  request.post('/api/contents/posts/', postForm.value).then(res => {
    if (res.code === 1) {
      postModalFlag.value = false
      // 路由跳转
      router.back()
      Modal.message({message: '保存成功，请等待审核', status: 'success', duration: 5000})
    } else {
      Modal.message({message: res.message, status: 'error'})
    }
  })
}

// 查询专栏列表
const queryColumnList = () => {
  request.get('/api/contents/posts/special-column/list').then(res => {
    if (res.code === 1) {
      columnList.value = res.data.map(col => {
        return {
          value: col.id,
          label: col.name
        }
      })
    } else {
      Modal.message({message: res.message, status: 'error'})
    }
  })
}
queryColumnList()

// 文件上传成功
const uploadSuccess = (res) => {
  if (res.code === 200) {
    coverImage.value = res.data
  }
}

// 保存文章
const saveArticle = () => {
  articleForm.value.tagIdList = tagValue.value.map(v => v[1])
  articleForm.value.content = text.value
  articleForm.value.coverImage = coverImage.value
  Modal.message({message: '文章正在保存...请稍后查看', status: 'warning', duration: 10000})
  articleModalFlag.value = false
  // router.back()
  request.post('/api/contents/articles/', articleForm.value).then(res => {
    if (res.code === 1) {
      // 路由跳转
      // router.push(`/content/manage/${currentUser.value.id}`)
      // Modal.message({message: '保存成功，请等待审核', status: 'success',duration:5000})
      Modal.message({message: res.data, status: 'success', duration: 5000})
    } else {
      Modal.message({message: res.message, status: 'error'})
    }
  })
}

// 查询标签列表
const queryTagList = () => {
  request.get('/api/systems/tags/tree').then(res => {
    if (res.code === 1) {
      tagList.value = res.data.map(tag => {
        const temp = {
          children: []
        }
        temp.value = tag.id
        temp.label = tag.name
        temp.children = tag.children.map(v => {
          const tmp = {
            value: 0,
            label: ''
          }
          tmp.value = v.id
          tmp.label = v.name
          return tmp
        })
        return temp
      })
      for (let i = 0; i < tagList.value.length; i++) {
        let temp = {}
        tagList.value[i].children.map(v => {
          temp.value = v.value
          temp.label = v.label
          tagChildren.value[temp.value] = temp.label
        })
      }
    } else {
      Modal.message({message: res.message, status: 'error'})
    }
  })
}
queryTagList()

// 处理标签选择
const handleChange = () => {
  // 判断标签数
  let len = tagValue.value.length
  if (len > 5) {
    Modal.message({message: '标签最多选择5个', status: 'warning'})
    // 移除多余的标签
    while (len > 5) {
      tagValue.value.pop()
      len--
    }
  }

  tagLabel.value = tagValue.value.map(tag => {
    return tagChildren.value[tag[1]]
  })
}

// 关闭预览图
const closeImgPreviewPic = () => {
  dialogVisible.value = false
}

// 预览图片
const previewPicture = (file) => {
  dialogImageUrl.value = file.url
  dialogVisible.value = true
}

// 移除图片
const removePicture = (file) => {
  pictureUpload.value.handleRemove(file)
}

// 打开提交表单模态框
const openSubmitForm = () => {
  if (type === '0') {
    articleModalFlag.value = true
    formTitle.value = '发布文章'
    articleForm.value.title = saveTitle.value
  } else {
    postModalFlag.value = true
    formTitle.value = '发布帖子'
    postForm.value.title = saveTitle.value
  }
}

// 查询文章信息
const queryArticle = () => {
  const articleId = route.query.articleId
  const userId = route.query.userId
  if (articleId !== undefined && articleId !== '' && userId !== undefined && userId !== '') {
    request.get(`/api/contents/articles/${articleId}/${userId}`).then(res => {
      if (res.code === 1) {
        articleForm.value = {...res.data}
        saveTitle.value = articleForm.value.title
        text.value = articleForm.value.content
        tagValue.value = res.data.tagList.map(v => v.id)
      } else {
        Modal.message({message: res.message, status: 'error'})
      }
    })
  }
}

onBeforeUnmount(() => {
  // 组件销毁时，也及时销毁编辑器
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})

onMounted(() => {
  title.value = type === '0' ? '输入文章标题...' : '输入帖子标题'
  text.value = type === '0' ? '' : '帖子不用输入'
  queryArticle()
})


</script>

<style lang="less" scoped>
.container {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-size: 100% 100%;
}

.header {
  .publishBtn {
    button {
      width: 100px;
      position: relative;
      overflow: hidden;
      border: 1px solid #18181a;
      border-radius: 5px;
      color: #18181a;
      display: inline-block;
      font-size: 15px;
      line-height: 15px;
      padding: 18px 18px 17px;
      text-decoration: none;
      cursor: pointer;
      background: #fff;
      user-select: none;
      -webkit-user-select: none;
      touch-action: manipulation;
      margin-left: 10px;
    }

    button span:first-child {
      position: relative;
      transition: color 600ms cubic-bezier(0.48, 0, 0.12, 1);
      z-index: 10;
    }

    button span:last-child {
      color: white;
      display: block;
      position: absolute;
      bottom: 0;
      transition: all 500ms cubic-bezier(0.48, 0, 0.12, 1);
      z-index: 100;
      opacity: 0;
      top: 50%;
      left: 50%;
      transform: translateY(225%) translateX(-50%);
      height: 14px;
      line-height: 13px;
    }

    button:after {
      content: "";
      position: absolute;
      bottom: -50%;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: black;
      transform-origin: bottom center;
      transition: transform 600ms cubic-bezier(0.48, 0, 0.12, 1);
      transform: skewY(9.3deg) scaleY(0);
      z-index: 50;
    }

    button:hover:after {
      transform-origin: bottom center;
      transform: skewY(9.3deg) scaleY(2);
    }

    button:hover span:last-child {
      transform: translateX(-50%) translateY(-50%);
      opacity: 1;
      transition: all 900ms cubic-bezier(0.48, 0, 0.12, 1);
    }
  }

  display: flex;
  align-items: center;
  position: sticky;
  top: 0;
}

.form-control {
  flex: 0.98;

  .input {
    color: #000;
    font-size: 26px;
    background-color: transparent;
    width: 100%;
    box-sizing: border-box;
    padding-inline: 0.5em;
    padding-block: 0.7em;
    border: none;
    border-bottom: var(--border-height) solid var(--border-before-color);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }

  .input-border {
    position: absolute;
    background: var(--border-after-color);
    width: 0%;
    height: 2px;
    bottom: 0;
    left: 0;
    transition: width 0.3s cubic-bezier(0.6, -0.28, 0.735, 0.045);
  }

  .input:focus {
    outline: none;
  }

  .input:focus + .input-border {
    width: 100%;
  }

  .input-alt {
    font-size: 26px;
    padding-inline: 1em;
    padding-block: 0.8em;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  }

  .input-border-alt {
    height: 3px;
    background: linear-gradient(90deg, #FF6464 0%, #FFBF59 50%, #47C9FF 100%);
    transition: width 0.4s cubic-bezier(0.42, 0, 0.58, 1.00);
  }

  .input-alt:focus + .input-border-alt {
    width: 100%;
  }

  position: relative;
  --width-of-input: 300px;
}

</style>
